import * as NaiveUI from 'naive-ui'
import type { MessageType, MessageReactive, MessageOptions, MessageApi, DialogOptions, DialogApi } from 'naive-ui'
import type { VNodeChild } from 'vue'
import { isNullOrUndef } from '@/utils'
import { useAppStore } from '@/store/modules/app'
import { computed } from 'vue'

export type MessageContentType = string | (() => VNodeChild)

export enum MessageTypeEnum {
  Create = 'create',
  Info = 'info',
  Success = 'success',
  Warning = 'warning',
  Error = 'error',
  Loading = 'loading'
}

export function setupMessage(NMessage: MessageApi) {
  let loadingMessage: MessageReactive | null = null
  class Message {
    /**
     * 规则：
     * * loading message只显示一个，新的message会替换正在显示的loading message
     * * loading message不会自动清除，除非被替换成非loading message，非loading message默认2秒后自动清除
     */

    removeMessage(message = loadingMessage, duration = 2000) {
      const timer = setTimeout(() => {
        if (message) {
          message.destroy()
          message = null
        }
        clearTimeout(timer)
      }, duration)
    }

    showMessage(type: MessageType, content: MessageContentType, option: MessageOptions = {}) {
      if (loadingMessage?.type === MessageTypeEnum.Loading) {
        // 如果存在则替换正在显示的loading message
        loadingMessage.type = type
        loadingMessage.content = content

        if (type !== MessageTypeEnum.Loading) {
          // 非loading message需设置自动清除
          this.removeMessage(loadingMessage, option.duration)
        }
      } else if (type !== 'default') {
        // 不存在正在显示的loading则新建一个message,如果新建的message是loading message则将message赋值存储下来
        const message = NMessage[type](content, option)
        if (type === MessageTypeEnum.Loading) {
          loadingMessage = message
        }
      }
    }

    loading(content: MessageContentType) {
      this.showMessage(MessageTypeEnum.Loading, content, { duration: 0 })
    }

    success(content: MessageContentType, option: MessageOptions = {}) {
      this.showMessage(MessageTypeEnum.Success, content, option)
    }

    error(content: MessageContentType, option: MessageOptions = {}) {
      this.showMessage(MessageTypeEnum.Error, content, option)
    }

    info(content: MessageContentType, option: MessageOptions = {}) {
      this.showMessage(MessageTypeEnum.Info, content, option)
    }

    warning(content: MessageContentType, option: MessageOptions = {}) {
      this.showMessage(MessageTypeEnum.Warning, content, option)
    }
  }

  return new Message()
}

type DialogInstance = DialogApi & {
  confirm: (_: DialogOptions) => Promise<unknown> | unknown
}
type DialogInstanceOptions = DialogOptions & {
  confirm?: () => Promise<unknown> | unknown
  cancel?: () => Promise<unknown> | unknown
}

export function setupDialog(NDialog: DialogInstance) {
  NDialog.confirm = function (option: DialogInstanceOptions = {}) {
    const showIcon = !isNullOrUndef(option.title)
    const type = !option.type || option.type === 'default' ? 'warning' : option.type
    return NDialog[type]({
      showIcon,
      positiveText: '确定',
      negativeText: '取消',
      onPositiveClick: option.confirm,
      onNegativeClick: option.cancel,
      onMaskClick: option.cancel,
      ...option
    })
  }

  return NDialog
}

export function setupNaiveDiscreteApi() {
  const appStore = useAppStore()
  const configProviderProps = computed(() => ({
    theme: appStore.isDark ? NaiveUI.darkTheme : undefined,
    themeOverrides: useAppStore().themeOverrides
  }))
  const { message, dialog, notification, loadingBar } = NaiveUI.createDiscreteApi(
    ['message', 'dialog', 'notification', 'loadingBar'],
    { configProviderProps }
  )

  window.$loadingBar = loadingBar
  window.$notification = notification
  window.$message = setupMessage(message)
  window.$dialog = setupDialog(dialog as DialogInstance)
}
